import QtQuick 2.0
import QtQuick.Window 2.2

Item {
    id: mynodes
    anchors.fill: parent

    property var _NODES_POOL: new Array
    property real gMoveSpeed: 1
    property real gMoveToMouseSpeed: 1
    property real gMoveToOtherSpeed: 0.6

    function getRandomDir()
    {
        if(getRandom(10) > 5) return 1;
        return -1;
    }

    function createNodePos()
    {
        if(_NODES_POOL.length > 100) return;
//        console.log("_NODES_POOL.length ", _NODES_POOL.length)

        var sx = getRandom(Screen.width-200)+100
        var sy = getRandom(Screen.height-200)+100
        var tx = getRandomDir() > 0 ? Screen.width : 0
        var ty = getRandomDir() > 0 ? Screen.height : 0

        var map = {}
        map.sx = sx; map.sy = sy; map.tx = tx; map.ty = ty;
        map.powerRadians = new Array;
        map.lineLens = new Array
        map.hasLineToOther = false;
        _NODES_POOL.push(map)
    }

    function calcDistance(x1, y1, x2, y2)
    {
        return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )
    }

    Timer{
        id: timer
        interval: 100
        repeat: true
        running: true
        onTriggered: {
            //
            createNodePos()
        }
    }

    Timer{
        interval: 50
        repeat: true
        running: true
        onTriggered: {
            canvas.requestPaint()
        }
    }

    Canvas{
        id: canvas
        anchors.fill: parent
        onPaint: {
            var ctx = getContext("2d");
            ctx.clearRect(0, 0, width, height)

            ctx.fillStyle = Qt.rgba(1, 1, 1, 1);
            ctx.strokeStyle = Qt.rgba(1, 1, 1, 1);
//            ctx.fillRect(0, 0, width, height);

            // 画点
            var len = _NODES_POOL.length
            for(var i in _NODES_POOL)
            {
                var map = _NODES_POOL[i]

                // 到达边界，删除点
                if(map.sx < 0)
                {
                    _NODES_POOL.splice(i, 1)
                    continue
                }
                else if(map.sx > Screen.width)
                {
                    _NODES_POOL.splice(i, 1)
                    continue
                }
                else if(map.sy < 0)
                {
                    _NODES_POOL.splice(i, 1)
                    continue
                }
                else if(map.sy > Screen.height)
                {
                    _NODES_POOL.splice(i, 1)
                    continue
                }

                ctx.beginPath();

                // move point
                var radian = Math.atan2(map.ty-map.sy,map.tx-map.sx)
                var moveSelfX = Math.cos(radian) * gMoveSpeed
                var moveSelfY = Math.sin(radian) * gMoveSpeed

                // 鼠标吸附点
                var radian2 = Math.atan2(gMouseY-map.sy,gMouseX-map.sx)

                var moveMouseX = 0
                var moveMouseY = 0

                var limits = 100
                if(calcDistance(map.sx, map.sy, gMouseX, gMouseY) <= limits)
                {
                    moveMouseX = Math.cos(radian2) * gMoveToMouseSpeed
                    moveMouseY = Math.sin(radian2) * gMoveToMouseSpeed
                }

                // 其他点 吸附力
                var moveFromOtherPointX = 0
                var moveFromOtherPointY = 0
                var moveFromOtherPointRadians = 0

                for(var p in map.powerRadians)
                {
                    moveFromOtherPointRadians += map.powerRadians[p]
                }
                if(map.powerRadians.length > 0)
                {
                    moveFromOtherPointRadians *= 1 / map.powerRadians.length

                    moveFromOtherPointX = Math.cos(moveFromOtherPointRadians) * gMoveToOtherSpeed
                    moveFromOtherPointY = Math.sin(moveFromOtherPointRadians) * gMoveToOtherSpeed
                }

                // calc
                if(moveMouseX !== 0 || moveMouseY !== 0)
                {
                    // 鼠标吸附
                    map.sx += moveMouseX
                    map.sy += moveMouseY
                }
                else if(map.hasLineToOther)
                {
                    map.sx += moveSelfX + moveFromOtherPointX
                    map.sy += moveSelfY + moveFromOtherPointY
                }
                else{
                    map.sx += moveSelfX
                    map.sy += moveSelfY
                }

                _NODES_POOL[i] = map

                ctx.arc(map.sx, map.sy, 2, 0, Math.PI*2, true);

                ctx.stroke();
                ctx.fill();

                ctx.closePath();

                // clean
                map.powerRadians = new Array
                map.hasLineToOther = false
            }

            // 连线
            var limits = 150
            len = _NODES_POOL.length
            for(var i = 0; i< len; ++i)
            {
                var map1 = _NODES_POOL[i]   // 当前点

//                // 防止多边形太多, 最大 三角形
//                if(map1.powerRadians.length > 1)
//                {
//                    // 用最短的线替换最长的线 TODO
//                    continue
//                }

                for(var j = i+1; j< len; ++j)
                {
//                    if(i == j) continue;
                    var map2 = _NODES_POOL[j]
                    if(calcDistance(map1.sx, map1.sy, map2.sx, map2.sy) <= limits)
                    {
                        // 防止多边形太多, 最大 三角形
                        if(map1.powerRadians.length > 1)
                        {
                            // 用最短的线替换最长的线 TODO
                            break
                        }

                        // 需要判断当前点是否已经被连过了
                        var ready = Math.atan2(map2.sy - map1.sy, map2.sx - map1.sx)
                        var hasExist = false
                        for(var k in map1.powerRadians)
                        {
                            if(ready === map1.powerRadians[k])
                            {
                                hasExist = true
                                break
                            }
                        }

                        if(hasExist === false)
                        {
                            map1.hasLineToOther = true
                            map2.hasLineToOther = true

                            // 为当前点计算受力
                            map1.powerRadians.push(ready)
                            map2.powerRadians.push(Math.atan2(map1.sy - map2.sy, map1.sx - map2.sx))

                            // 需要连线
                            ctx.beginPath();
                            ctx.moveTo(map1.sx, map1.sy)
                            ctx.lineTo(map2.sx, map2.sy)
                            ctx.stroke();

                            ctx.closePath();
                        }

                    }
                }
            }
        }
    }
}
